package com.money.tracker.auth.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.money.tracker.common.utils.LoginUtil;
import com.money.tracker.common.utils.StreamUtil;
import com.money.tracker.auth.entity.SysMenu;
import com.money.tracker.auth.entity.rsp.RouterRsp;
import com.money.tracker.auth.enums.MenuStatusEnum;
import com.money.tracker.auth.enums.MenuTypeEnum;
import com.money.tracker.auth.mapper.SysMenuMapper;
import com.money.tracker.auth.service.ISysMenuService;
import com.money.tracker.auth.service.ISysRoleMenuService;
import com.money.tracker.auth.service.ISysUserRoleService;
import com.money.tracker.auth.service.transfer.SysTransferService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单权限表 服务实现类
 * </p>
 *
 * @author zhangshuai
 * @since 2024-09-28
 */
@Service
@RequiredArgsConstructor
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {

    private final ISysUserRoleService userRoleService;
    private final ISysRoleMenuService roleMenuService;
    private final SysTransferService sysTransferService;

    @Override
    public Set<String> getMenuPermissionByUserId(Long userId) {
        // 获取用户角色对应关系
        List<Long> roleIds = userRoleService.listByUserId(userId);
        if (CollectionUtil.isEmpty(roleIds)){
            return Collections.emptySet();
        }
        // 获取角色权限
        List<Long> menuIds = roleMenuService.listByRoleIds(roleIds);
        LambdaQueryWrapper<SysMenu> lambdaQueryWrapper = new LambdaQueryWrapper<SysMenu>()
                .in(SysMenu::getId, menuIds);
        return StreamUtil.toSet(this.list(lambdaQueryWrapper), SysMenu::getPerms);
    }

    @Override
    public List<RouterRsp> getRouters() {
        LambdaQueryWrapper<SysMenu> lqw = new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getStatus, MenuStatusEnum.NORMAL.getCode())
                .orderByAsc(SysMenu::getParentId)
                .orderByAsc(SysMenu::getOrderNum);
        // 管理员获取所有菜单
        if (LoginUtil.isAdmin()) {
            lqw.in(SysMenu::getMenuType, MenuTypeEnum.MENU.getCode(), MenuTypeEnum.CATALOG.getCode());
        } else {
            // 拿当前登录用户菜单权限
            lqw.in(SysMenu::getPerms, LoginUtil.getLoginUser().getMenuPermission());
        }
        List<SysMenu> sysMenus = this.list(lqw);
        // 拼装子菜单
        sysMenus = buildChildPerms(sysMenus, 0L);
        return sysTransferService.buildRouterRsp(sysMenus);
    }

    /**
     * 根据传入的某个父节点ID,遍历该父节点的所有子节点---> 简单递归
     *
     * @param sysMenus
     * @param parentId
     * @return {@link List }<{@link SysMenu }>
     */
    private List<SysMenu> buildChildPerms(List<SysMenu> sysMenus, Long parentId) {
        Map<Long, List<SysMenu>> sysMenuMap = StreamUtil.groupByKey(sysMenus, SysMenu::getParentId);
        List<SysMenu> menus = sysMenuMap.get(parentId);
        if (CollectionUtil.isEmpty(menus)) {
            return new ArrayList<>();
        }
        return menus.stream()
                .peek(sysMenu -> sysMenu.setChildren(buildChildPerms(sysMenus, sysMenu.getId())))
                .collect(Collectors.toList());
    }
}
